﻿using Caliburn.Micro;
using SD.Common;
using SD.Infrastructure.DTOBase;
using SD.Infrastructure.WPF.Caliburn.Aspects;
using SD.Infrastructure.WPF.Caliburn.Base;
using SD.IOC.Core.Mediators;
using SlamDunk.MES.Client.ViewModels.Facility;
using SlamDunk.MES.Client.ViewModels.StockQuery;
using SlamDunk.MES.IAppService.DTOs.Outputs.ResourceContext;
using SlamDunk.MES.IAppService.Interfaces;
using SlamDunk.MES.Presentation.Maps;
using SlamDunk.MES.Presentation.Models.NotifyModels;
using SlamDunk.MES.ReportView.Models;
using SlamDunk.ValueObjects.Enums;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.ServiceModel.Extensions;
using System.Threading.Tasks;
using System.Windows;

namespace SlamDunk.MES.Client.ViewModels.StockSettlement
{
    /// <summary>
    /// 库存结转添加ViewModel
    /// </summary>
    public class AddViewModel : ScreenBase
    {
        #region # 字段及构造器

        /// <summary>
        /// 库存单据服务契约接口代理
        /// </summary>
        private readonly ServiceProxy<IStockOrderContract> _iStockOrderContract;

        /// <summary>
        /// 资源定义服务契约接口代理
        /// </summary>
        private readonly ServiceProxy<IResourceContract> _iResourceContract;

        /// <summary>
        /// 基础定义服务契约接口代理
        /// </summary>
        private readonly ServiceProxy<IFoundationContract> _iFoundationContract;

        /// <summary>
        /// 编号生成服务契约接口代理
        /// </summary>
        private readonly ServiceProxy<INumberContract> _iNumberContract;

        /// <summary>
        /// 库存管理服务契约接口代理
        /// </summary>
        private readonly ServiceProxy<IStockManageContract> _iStockManageContract;


        /// <summary>
        /// 窗口管理器
        /// </summary>
        private readonly IWindowManager _windowManager;

        /// <summary>
        /// 依赖注入构造器
        /// </summary>
        public AddViewModel(ServiceProxy<IStockOrderContract> iStockOrderContract, ServiceProxy<IResourceContract> iResourceContract, ServiceProxy<IFoundationContract> iFoundationContract, ServiceProxy<INumberContract> iNumberContract, ServiceProxy<IStockManageContract> iStockManageContract, IWindowManager windowManager)
        {
            this._iStockOrderContract = iStockOrderContract;
            this._iResourceContract = iResourceContract;
            this._iFoundationContract = iFoundationContract;
            this._iStockManageContract = iStockManageContract;
            this._windowManager = windowManager;
            this._iNumberContract = iNumberContract;
        }
        #endregion

        #region 属性
        #region 工厂模型名称
        /// <summary>
        /// 工厂模型名称
        /// </summary>
        [DependencyProperty]
        public string FacilityName { get; set; }
        #endregion

        #region 工厂模型Id
        /// <summary>
        /// 工厂模型Id
        /// </summary>
        [DependencyProperty]
        public Guid? FacilityId { get; set; }
        #endregion

        #region 储存位置类型
        /// <summary>
        /// 储存位置类型
        /// </summary>
        [DependencyProperty]
        public IDictionary<string, string> StorageLocationTypes { get; set; }
        #endregion

        #region 库位列表
        /// <summary>
        /// 库位列表
        /// </summary>
        [DependencyProperty]
        public ObservableCollection<IdentiferNameNm> StorageLocations { get; set; }
        #endregion

        #region 已选储存位置类型
        /// <summary>
        /// 已选储存位置类型
        /// </summary>
        [DependencyProperty]
        public StorageLocationType? SelectedStorageLocationType { get; set; }
        #endregion

        #region 已选库位列表
        /// <summary>
        /// 已选库位列表
        /// </summary>
        [DependencyProperty]
        public IdentiferNameNm SelectedStorageLocation { get; set; }
        #endregion

        #region 库位列表显示隐藏
        /// <summary>
        /// 库位列表显示隐藏
        /// </summary>
        [DependencyProperty]
        public Visibility StorageLocationComboBoxVisibility { get; set; }
        #endregion

        #region 库位描述显示隐藏
        /// <summary>
        /// 库位描述显示隐藏
        /// </summary>
        [DependencyProperty]
        public Visibility StorageLocationTextVisibility { get; set; }
        #endregion

        #region 库位描述
        /// <summary>
        /// 库位描述
        /// </summary>
        [DependencyProperty]
        public string StorageLocationText { get; set; }
        #endregion

        #region 物料定义列表
        /// <summary>
        /// 物料定义列表
        /// </summary>
        [DependencyProperty]
        public ObservableCollection<MaterialInfo> Materials { get; set; }
        #endregion

        #region 已选物料定义 —— MaterialInfo SelectedMaterial
        /// <summary>
        /// 已选物料定义
        /// </summary>
        [DependencyProperty]
        public MaterialInfo SelectedMaterial { get; set; }
        #endregion

        #region 物料批次Id
        /// <summary>
        /// 物料批次Id
        /// </summary>
        [DependencyProperty]
        public Guid? materialLotId { get; set; }
        #endregion

        #region 物料批次名称
        /// <summary>
        /// 物料批次名称
        /// </summary>
        [DependencyProperty]
        public string MaterialLotName { get; set; }
        #endregion

        #region 结转日期
        /// <summary>
        /// 结转日期
        /// </summary>
        [DependencyProperty]
        public DateTime? SettledDate { get; set; }
        #endregion

        #region 数量
        /// <summary>
        /// 数量
        /// </summary>
        [DependencyProperty]
        public decimal Quantity { get; set; }
        #endregion

        #region 描述
        /// <summary>
        /// 描述
        /// </summary>
        [DependencyProperty]
        public string Description { get; set; }
        #endregion

        #endregion

        #region 方法

        #region 加载 —— async Task Load(AddViewModel addViewModel)
        /// <summary>
        /// 加载
        /// </summary>
        public async Task Load()
        {
            //初始化存储位置类型
            this.StorageLocationTypes = typeof(StorageLocationType).GetEnumMembers();
            //分页获取物料定义列表
            PageModel<MaterialInfo> MaterialList = await Task.Run(() => this._iResourceContract.Channel.GetMaterialsByPage(
                null,//关键字
                null, //物料来源类型
                null,//是否按批量管理
                this.FacilityId,//工厂模型Id
                null, //是否启用
                null,//物料类Id
                1,//页码
                int.MaxValue));
            this.Materials = new ObservableCollection<MaterialInfo>(MaterialList.Datas);
            this.SettledDate = DateTime.Now;
        }
        #endregion

        #region 清空工厂模型 —— async void ClearFacility()
        /// <summary>
        /// 清空工厂模型
        /// </summary>
        public async void ClearFacility()
        {
            this.FacilityId = null;
            this.FacilityName = "";
        }
        #endregion

        #region 加载工厂模型-弹出层
        /// <summary>
        /// 加载工厂模型-弹出层
        /// </summary>
        public async void SelectFacility()
        {
            this.Busy();
            SelectFacilityViewModel viewModel = ResolveMediator.Resolve<SelectFacilityViewModel>();
            bool? result = await this._windowManager.ShowDialogAsync(viewModel);
            if (result == true)
            {
                this.FacilityId = viewModel.SelectedFacility.Id;
                this.FacilityName = viewModel.SelectedFacility.Name;
            }
            this.Idle();
        }
        #endregion

        #region 加载储存位置
        /// <summary>
        /// 加载储存位置
        /// </summary>
        public async void LoadStorageLocation()
        {
            this.Busy();

            await this.ReloadStorageLocation();

            this.Idle();
        }
        #endregion

        #region 清空 物料定义 —— async void ClearMaterial()
        /// <summary>
        /// 清空工厂模型
        /// </summary>
        public async void ClearMaterial()
        {
            this.materialLotId = null;
            this.MaterialLotName = "";
        }
        #endregion

        #region 物料定义选中事件
        /// <summary>
        /// 物料定义选中事件
        /// </summary>
        public async void SelectMaterial()
        {
            if (this.SelectedMaterial != null)
            {
                SelectMaterialStockViewModel viewModel = ResolveMediator.Resolve<SelectMaterialStockViewModel>();
                var storageLocationTxt = this.SelectedStorageLocationType == StorageLocationType.Description ? this.StorageLocationText : this.SelectedStorageLocation?.Id.ToString();
                viewModel.Load(this.FacilityId, this.SelectedMaterial?.Id, this.SelectedStorageLocationType, storageLocationTxt, false);
                bool? result = await this._windowManager.ShowDialogAsync(viewModel);
                if (result == true)
                {
                    MaterialStockInfo materialStockInfo = viewModel.MaterialStocks.Where(x => x.IsChecked == true).Select(x => x.Model).FirstOrDefault();
                    this.materialLotId = materialStockInfo.MaterialLotId;
                    this.MaterialLotName = materialStockInfo.ProductionBatchNo;
                }
            }
            else
            {
                MessageBox.Show("请选择物料定义！", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
                return;
            }
        }
        #endregion

        #region 提交 —— async void Submit()
        /// <summary>
        /// 提交
        /// </summary>
        public async void Submit()
        {
            #region # 验证
            if (this.SelectedMaterial == null)
            {
                MessageBox.Show("请选择物料定义！", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
                return;
            }
            if (this.SelectedStorageLocationType == null)
            {
                MessageBox.Show("请选择存储位置类型！", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
                return;
            }
            if (this.SelectedStorageLocation == null && string.IsNullOrEmpty(this.StorageLocationText))
            {
                MessageBox.Show("请选择储存位置！", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
                return;
            }
            #endregion

            this.Busy();
            await Task.Run(() => this._iStockManageContract.Channel.SettleStock(
                this.SelectedMaterial.Id,//物料定义Id
                this.materialLotId,//物料批次Id
                null,//物料批次参数模型
                this.SelectedStorageLocationType.Value,//储存位置类型
                this.SelectedStorageLocation.Id.ToString(),//目标储存位置Id
                this.SelectedStorageLocationType == StorageLocationType.Description ? this.StorageLocationText : this.SelectedStorageLocation.Name,
                this.SettledDate.Value,//结转日期
                this.Quantity,//数量
                this.FacilityId,//工厂模型Id
                this.Description//描述
                ));
            await base.TryCloseAsync(true);
            this.Idle();
        }
        #endregion

        //Private
        #region 加载储存位置列表 —— async Task ReloadStorageLocation()
        /// <summary>
        /// 加载储存位置列表
        /// </summary>
        public async Task ReloadStorageLocation()
        {
            #region # 验证

            if (this.SelectedStorageLocationType == null)
            {
                this.StorageLocations = new ObservableCollection<IdentiferNameNm>();
                return;
            }
            #endregion

            //显示隐藏库位列表
            this.StorageLocationComboBoxVisibility = Visibility.Visible;
            this.StorageLocationTextVisibility = Visibility.Collapsed;
            switch (this.SelectedStorageLocationType)
            {
                case StorageLocationType.ProductionDomain://生产域
                    IEnumerable<IAppService.DTOs.Outputs.FoundationContext.FacilityInfo> Facilities = await Task.Run(() =>
                    this._iFoundationContract.Channel.GetFacilities(
                        null,//关键字
                        null,//工厂模型层次
                        FacilityType.ProductionDomain,//工厂模型类型
                        null)//上级节点Id
                    );
                    IEnumerable<IdentiferNameNm> Facilitiemodels = Facilities.Select(x => x.ToIdentiferName());
                    this.StorageLocations = new ObservableCollection<IdentiferNameNm>(Facilitiemodels);
                    break;
                case StorageLocationType.BusinessDomain://业务域
                    Facilities = await Task.Run(() =>
                    this._iFoundationContract.Channel.GetFacilities(
                        null,//关键字
                        null,//工厂模型层次
                        FacilityType.BusinessDomain,//工厂模型类型
                        null)//上级节点Id
                    );
                    Facilitiemodels = Facilities.Select(x => x.ToIdentiferName());
                    this.StorageLocations = new ObservableCollection<IdentiferNameNm>(Facilitiemodels);
                    break;
                case StorageLocationType.StorageDomain://储存域
                    Facilities = await Task.Run(() =>
                   this._iFoundationContract.Channel.GetFacilities(
                      null,//关键字
                      null,//工厂模型层次
                      FacilityType.StorageDomain,//工厂模型类型
                      null)//上级节点Id
                  );
                    Facilitiemodels = Facilities.Select(x => x.ToIdentiferName());
                    this.StorageLocations = new ObservableCollection<IdentiferNameNm>(Facilitiemodels);
                    break;
                case StorageLocationType.Person://人员
                    PageModel<PersonInfo> Persons = await Task.Run(() =>
                      this._iResourceContract.Channel.GetPersonsByPage(
                         null,//关键字
                         this.FacilityId,//工厂模型Id
                         null,//人员类Id
                         1,
                         int.MaxValue)//上级节点Id
                   );
                    IEnumerable<IdentiferNameNm> Personsmodels = Persons.Datas.Select(x => x.ToIdentiferName());
                    this.StorageLocations = new ObservableCollection<IdentiferNameNm>(Personsmodels);
                    break;
                case StorageLocationType.Team://班组
                    PageModel<TeamInfo> Teams = await Task.Run(() =>
                     this._iResourceContract.Channel.GetTeamsByPage(
                        null,//关键字
                        this.FacilityId,//工厂模型Id
                        1,
                        int.MaxValue)//上级节点Id
                  );
                    IEnumerable<IdentiferNameNm> TeamModels = Teams.Datas.Select(x => x.ToIdentiferName());
                    this.StorageLocations = new ObservableCollection<IdentiferNameNm>(TeamModels);
                    break;
                case StorageLocationType.Customer://客户
                    PageModel<EnterpriseInfo> Enterprises = await Task.Run(() =>
                    this._iResourceContract.Channel.GetEnterprisesByPage(
                       null,//关键字
                       EnterpriseType.Customer,//工厂模型Id
                       null,
                       1,
                       int.MaxValue)//上级节点Id
                 );
                    IEnumerable<IdentiferNameNm> EnterpriseModels = Enterprises.Datas.Select(x => x.ToIdentiferName());
                    this.StorageLocations = new ObservableCollection<IdentiferNameNm>(EnterpriseModels);
                    break;
                case StorageLocationType.Supplier://供应商
                    Enterprises = await Task.Run(() =>
                   this._iResourceContract.Channel.GetEnterprisesByPage(
                      null,//关键字
                      EnterpriseType.Supplier,//工厂模型Id
                      null,
                      1,
                      int.MaxValue)//上级节点Id
                );
                    EnterpriseModels = Enterprises.Datas.Select(x => x.ToIdentiferName());
                    this.StorageLocations = new ObservableCollection<IdentiferNameNm>(EnterpriseModels);
                    break;
                case StorageLocationType.Description://描述
                    this.StorageLocationComboBoxVisibility = Visibility.Collapsed;
                    this.StorageLocationTextVisibility = Visibility.Visible;
                    break;
            }
        }
        #endregion
        #endregion
    }
}
